import sys

import threading, time
from queue import Queue

from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

from match_server.match import Match
from match_server.match.ttypes import User
from return_client.match_success.MatchSuccess import Client

class User:
    def __init__(self, name, score):
        self.name = name
        self.score = score


class Task:
    def __init__(self, user, type):
        self.user = user
        self.type = type


class Message_queue:
    def __init__(self):
        self.q = Queue()
        self.cv = threading.Condition()


class MatchHandler:

    def add_user(self, user, info):
        print("add_user")
        message_queue.q.put(Task(user, "add"))
        return 0

    def remove_user(self, user, info):
        print("remove_user")
        message_queue.q.put(Task(user, "remove"))
        return 0


class Pool:
    def __init__(self):
        self.__users = []
        self.__wt = []

    def remove(self, user):
        for i, e in enumerate(self.__users):
            if e.name == user.name:
                self.__users.remove(e)
                self.__wt.remove(self.__wt[i])
                break

    def add_user(self, user):
        for e in self.__users:
            if e.name == user.name:
                return
        self.__users.append(user)
        self.__wt.append(0)

    def __check_match(self, x, y):
        dt = abs(self.__users[x].score - self.__users[y].score)
        a_diff = self.__wt[x] * 500
        b_diff = self.__wt[y] * 500
        return dt <= a_diff and dt <= b_diff

    def __match_success(self, x, y):
        # Make socket
        transport = TSocket.TSocket('127.0.0.1', 9091)

        # Buffering is critical. Raw sockets are very slow
        transport = TTransport.TBufferedTransport(transport)

        # Wrap in a protocol
        protocol = TBinaryProtocol.TBinaryProtocol(transport)

        # Create a client to use the protocol encoder
        client = Client(protocol)

        # Connect!
        transport.open()

        client.match_success(x, y)

        # Close!
        transport.close()
        return 0

    def match(self):
        for i in range(len(self.__wt)):
            self.__wt[i] += 1
        while len(self.__users) > 1:
            matched = False
            for i in range(len(self.__users)):
                j = i + 1
                while j < len(self.__users):
                    if self.__check_match(i, j):
                        a, b = self.__users[i], self.__users[j]
                        ta, tb = self.__wt[i], self.__wt[j]
                        self.__users.remove(a)
                        self.__users.remove(b)
                        self.__wt.remove(ta)
                        self.__wt.remove(tb)
                        matched = True
                        print("match: %s %s" % (a.name, b.name))
                        self.__match_success(a.name, b.name)
                        break
                    j += 1
                if matched:
                    break
            if not matched:
                break


message_queue = Message_queue()
pool = Pool()


class Consumer(threading.Thread):
    def __init__(self, t_name):
        threading.Thread.__init__(self, name=t_name)

    def run(self):
        while True:
            if message_queue.q.empty():
                pool.match()
                time.sleep(1)
            else:
                task = message_queue.q.get()
                if task.type == "add":
                    pool.add_user(task.user)
                elif task.type == "remove":
                    pool.remove(task.user)



handler = MatchHandler()
processor = Match.Processor(handler)
transport = TSocket.TServerSocket(host='127.0.0.1', port=9090)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()

server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)

    # You could do one of these for a multithreaded server
    # server = TServer.TThreadedServer(
    #     processor, transport, tfactory, pfactory)
    # server = TServer.TThreadPoolServer(
    #     processor, transport, tfactory, pfactory)
consumer = Consumer("consumer")
consumer.start()

print('Starting the server...')
server.serve()
print('done.')
